iT邦幫忙

2026 iThome 鐵人賽

DAY 4
0
JavaScript

QA 的 JavaScript 初心之路:30 天做出一個能玩的戰鬥小遊戲《勇者 vs 小怪》系列 第 4

Day04|條件判斷與邊界測試:HP 剛好 30,算不算重傷?

  • 分享至 

  • xImage
  •  

今天的主題:if/else 條件判斷

今天正式碰到 QA 熟悉的東西——條件判斷。基本語法是這樣:

let hp = 50;

if (hp <= 0) {
  console.log("勇者陣亡");
} else if (hp < 30) {
  console.log("勇者身受重傷");
} else {
  console.log("勇者狀態正常");
}

邏輯是由上往下依序檢查,只要有一個條件成立就執行對應區塊,後面就不再檢查。

=== 還是 ==?我先猜錯了一次

JavaScript 有兩種「等於」:=====。在動手測之前,我先猜了一下 0 == false0 === false 這兩個算式的結果,我猜兩個都是 false——畢竟 0 是數字、false 是布林,型別不一樣,感覺怎麼比都不該相等。

實際跑了才發現我猜錯一半:

console.log(0 == false);   // true
console.log(0 === false);  // false

插入 day4.png:Console 顯示 0 == false 與 0 === false 的實際結果

0 == false 居然是 true,0 === false 才是我原本以為的 false。查了才搞懂:== 在比較之前,會先偷偷把兩邊的型別轉成同一種再比(false 被轉成數字 0 之後,兩邊就相等了),而 === 不會做這個轉換,型別不一樣就直接判定不相等。

用 QA 的角度看,== 這種「偷偷幫你轉型別再比」的行為,很容易讓型別不對的問題被矇混過關;=== 的嚴格比對更接近測試斷言該有的態度——不相等就是不相等,不會因為背後偷做轉換而放水。這次的練習我全程只用 ===

動手驗證邊界值

我寫了一個判斷 HP 狀態的函式:

function checkStatus(hp) {
  if (hp <= 0) {
    console.log(hp, "→ 勇者陣亡");
  } else if (hp < 30) {
    console.log(hp, "→ 身受重傷");
  } else {
    console.log(hp, "→ 狀態正常");
  }
}

//帶入不同數值看看會出什麼結果
checkStatus(100);
checkStatus(20);
checkStatus(0);
checkStatus(-10);

四個測試案例的結果都符合預期:

100 → 狀態正常
20  → 身受重傷
0   → 勇者陣亡
-10 → 勇者陣亡

插入 day4-2.png:四個測試案例的 Console 輸出

但我沒有就此停手,而是想到還有一個邊界沒測到:HP 剛好等於 30 會怎樣?

跑了 checkStatus(30),結果是「狀態正常」——因為條件是 hp < 30(嚴格小於),30 < 30false,所以直接跳到 else

插入 day4-3.png:加入 checkStatus(30) 後的 Console 輸出,可見 30 → 狀態正常

這裡我停下來想了一下:這個結果符合原本的意圖嗎? 我認為是符合的——既然條件寫的是「小於 30 才算重傷」,那「大於等於 30」理所當然都算未陣亡的正常狀態,30 本來就該落在「正常」這一邊,不是漏洞。

但我還是決定在程式碼裡補一行註解,標明這個邊界的判斷方式,原因是:「30 剛好落在哪一邊」這種問題,如果沒有寫下來,幾個月後回頭看程式碼、或是別人接手時,很容易搞不清楚這是刻意設計還是不小心漏掉。與其讓人猜,不如當下就寫清楚:

} else {
  console.log(hp, "→ 狀態正常");  // 註:30 本身不算重傷,30 以上都算正常
}

這是我在 QA 工作裡學到的習慣:邊界值不只要測,測完之後的判斷理由,也值得留下紀錄,不然「這是故意的」和「這是漏洞」看起來會一模一樣。

順手釐清一下:checkStatus 是什麼意思?

寫這段程式碼時,我一度把 function 這個關鍵字跟 Python 的 input()搞混,後來查證後確認:

  • function(JS)對應的其實是 Python 的 def,兩者都是「定義一個可重複呼叫的函式」
  • 真正對應 Python input()(跟使用者要輸入值)的,是 JS 的 prompt(),這次練習完全沒用到

另外 checkStatus 本身不是 JavaScript 的關鍵字,是我自己取的名字,單純因為這個函式的功能是「檢查狀態」,取這個名字方便理解,換成別的名字功能也一樣。JS 圈子習慣用「駝峰式命名」(第一個字小寫,後面每個新單字開頭大寫),像 checkStatusheroName 都是這樣寫。

小結

今天搞懂的事:

  • 0 == false 是 true、0 === false 才是 false,跟我原本的直覺相反,因為 == 會偷偷做型別轉換再比較——之後一律用 ===
  • 測邊界值不能只測「明顯正常」跟「明顯異常」,一定要測臨界點本身(這次是 HP 剛好等於 30)
  • 臨界點測完之後,還要判斷這個結果是不是自己原本想要的設計,並且留下註解說明,避免「故意的」跟「漏洞」被搞混
  • function 對應 Python 的 def,不是 input();函式名稱是自己取的,不是關鍵字

明天繼續學陣列——一群資料的容器。


上一篇
Day03|字串與模板字串:蛋糕和岩石都能拿來拼
下一篇
Day05|陣列與索引:爬樓梯還是搭電梯?
系列文
QA 的 JavaScript 初心之路:30 天做出一個能玩的戰鬥小遊戲《勇者 vs 小怪》7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言